{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Why augmentation?\n",
    "Simply according to the [paper](https://arxiv.org/abs/1711.08324), Data augmentation is used to alleviate the over-fitting problem.\n",
    "\n",
    "Also, we should use 3d patches (sub-images) instead of the whole image. This is because: \"[it] is infeasible for our 3D CNN [to use the entire image as input to the models] due to the GPU memory constraint. When the resolution of lung scans is kept at a fine level, even a single sample consumes more than the maximum memory of mainstream GPUs.\"\n",
    "These patches are sized 128\\*128\\*128 for height, length, and width respectively.\n",
    "At their paper, they have said that:\n",
    "\n",
    "`Two kinds of patches are randomly selected. First, 70% of the inputs are selected so that they contain at least one nodule. Second, 30% of the inputs are cropped randomly from lung scans and may not contain any nodules.`\n",
    "\n",
    "And I have covered this at `prepare/run` file of this repository. The code is quite easy.\n",
    "\n",
    "Anyway, I want to describe `Resize`, `Random Cropping`, and `Rotation` which are mentioned in the paper. Actually, they have not coded the `Rotation` part and just flip the image, but I thought it would be great for the augmentation part if I cover it."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Resize\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "from PIL import Image\n",
    "from glob import glob\n",
    "import pandas as pd\n",
    "import skimage, os\n",
    "from skimage.morphology import ball, disk, dilation, binary_erosion, remove_small_objects, erosion, closing, reconstruction, binary_closing\n",
    "from skimage.measure import label,regionprops, perimeter\n",
    "from skimage.morphology import binary_dilation, binary_opening, convex_hull_image\n",
    "from skimage.filters import roberts, sobel\n",
    "from skimage import measure, feature\n",
    "from skimage.segmentation import clear_border\n",
    "from skimage import data\n",
    "from scipy import ndimage as ndi\n",
    "import matplotlib.pyplot as plt\n",
    "from mpl_toolkits.mplot3d.art3d import Poly3DCollection\n",
    "import pydicom\n",
    "import scipy.misc\n",
    "import numpy as np\n",
    "import SimpleITK as sitk"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "def scale(img: np.array, scale_factor: float, spacing: tuple, centers: list, radii: list):\n",
    "    # original values is between 0.8 and 1.15\n",
    "    assert (.75 <= scale_factor <= 1.25)\n",
    "    out_centers = [tuple(np.rint(np.array(c) * scale_factor).astype(int)) for c in centers]\n",
    "    out_radii = [r * scale_factor for r in radii]\n",
    "    spacing = np.array(spacing) * scale_factor\n",
    "    img1 = scipy.ndimage.interpolation.zoom(img, spacing, mode='nearest')\n",
    "    return img1, tuple(spacing), out_centers, out_radii"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "To test the functionality of this method, we need an argmax for 3d array. But there is no such method, so we write something like this to overcome the problem:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "def argmax_3d(img: np.array):\n",
    "    max1 = np.max(img, axis=0)\n",
    "    argmax1 = np.argmax(img, axis=0)\n",
    "    max2 = np.max(max1, axis=0)\n",
    "    argmax2 = np.argmax(max1, axis=0)\n",
    "    argmax3 = np.argmax(max2, axis=0)\n",
    "    argmax_3d = (argmax1[argmax2[argmax3], argmax3], argmax2[argmax3], argmax3)\n",
    "    return argmax_3d, img[argmax_3d]\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "All of these methods which I implemented, work for both 2d and 3d images. So first I show you the 2d one, then we will work on the 3d image.\n",
    "\n",
    "First, Let's create a black and white image."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "black_white = np.zeros((100,100))\n",
    "centers = [(25,25), (25,35)]\n",
    "for i in range(50):\n",
    "    black_white[i, 0:50] = np.ones(50)\n",
    "\n",
    "# creating fake nodule\n",
    "for center in centers:\n",
    "    for i in [-1,0,1]:\n",
    "        for j in [-1,0,1]:\n",
    "            black_white[center[0] + i, center[1] + j] = 0.\n",
    "from matplotlib import pyplot as plt\n",
    "plt.imshow(black_white, cmap=plt.cm.gray)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Then we resize it:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "shape (78, 78)\n",
      "(0.7755605556043104, 0.7755605556043104) [0.7755605556043104, 1.5511211112086207]\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAPsAAAD7CAYAAACscuKmAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy86wFpkAAAACXBIWXMAAAsTAAALEwEAmpwYAAAQmUlEQVR4nO3db4wc9X3H8fdn9v747NiYgxT/OYxdxQL5AZj0RLGIqmBCRVMEeYAsaIiiCMlP0grURCnkUSs1EuFBEh5UVBaQUokGCEkEQogUUaS2UuX6+NMCtil/iuWz8J/GPgw+7Lvb/fbBzi57Zu2bu93bu73f5yWtdmdmb+a3mv3szPxmbr6KCMxs6csWugFm1hkOu1kiHHazRDjsZolw2M0S4bCbJaKlsEu6SdLbkt6VdG+7GmVm7ae5nmeXVAL+B7gRGAX2AHdExN72Nc/M2qWnhb+9Bng3It4HkPQEcCtwzrAPDg7G0NBQC4u0+RQRSCLLMiQxPj7O4cOHGR8fr49vfK8tPlNTU5TLZTWb1krY1wMHG4ZHgT883x8MDQ3x/PPPt7BImy+VSoVyuUypVGL58uX09fUxMjLCAw88wKuvvkpfXx8DAwOUSiXK5TKVSoVKpTLtB8AW3ujo6DmnzfuakrRT0oikkePHj8/34szsHFoJ+yHg0obhoXzcNBGxKyKGI2J4cHCwhcWZWStaCfseYLOkTZL6gNuBZ9vTLDNrtzkfs0fElKQ/B34LlIBHI+KttrXMzNqqlQ46IuJ5wD1uZl3AXalmiXDYzRLhsJslwmE3S4TDbpYIh90sEQ67WSIcdrNEOOxmiXDYzRLhsJslwmE3S4TDbpYIh90sEQ67WSIcdrNEOOxmiXDYzRLhsJslYsawS3pU0lFJbzaMG5T0oqR38ucL57eZZtaqIlv2fwBuOmvcvcBLEbEZeCkfNrNFbMawR8S/AmeXcrkVeCx//RjwjfY2y8zaba7H7JdExIf568PAJW1qj5nNk5Y76KJazvOcJT1d681scZhr2I9IWguQPx891xtd681scZhr2J8Fvp2//jbwTHuaY2bzpcipt18A/wFcLmlU0l3A/cCNkt4BvpYPm9kiNmOtt4i44xyTbmhzW8xsHvkKOrNEOOxmiXDYzRLhsJslwmE3S4TDbpYIh90sEQ67WSIcdrNEOOxmiZjxclk7vyxr/ntZqVQW5XwtXd6yzwMH0hYjb9lbVKlUqN6/o0pS2+Zr1k4Oe4vODjtUA3+u3fCZ1OYVEW2dr5nD3oKIaBr2VgN5rvk67NYKh32OIoJyucyZM2eYnJycNq2/v59ly5bNepe+UqlQLpeJCKamppiamqJSqdQDXiqVyLKMnp6e+vvNinLY56C2i12pVJiYmGBiYqI+TRKlUomImHXYaz8gEcHExASTk5PT5tPb21v/ETl7q282E4d9lmqBrFQqnDp1igMHDnDy5Mn6dEmsWbOGyy67jL6+vvrf1KY1U9tynz59mo8//pjJyUlOnDjBRx99VA+7JFatWsWmTZtYvnx5vQ1z+VGxNDnsM6gFsVKp1B9nzpxhYmKCgwcP8swzz7B3795p79++fTu33XYbfX190469syz7XDBru+YRwdjYGO+99x6ffPIJb7zxBnv37mVqaoqenh6yLGPz5s3ceeedrFu3jsnJyWm7+Q68zWTGsEu6FPhHqoUgAtgVEQ9KGgSeBDYCHwA7IuLE/DV1YdV23SOCyclJJiYmGBsb480332T37t319/T09LBx48Zpu/aVSqUexmYdbLVpp0+f5tixY4yNjbF//3727NkzLezlcplPP/20/iPS2C6H3WZSpGt3CvheRGwBrgW+K2kLrvfW1HwcS/v43NqhSK23DyPi1fz1x8A+YD2u91Z39jnxdoWz2bl2aN+FO5aWWR2zS9oIXA3sJrF6b80CVut57+npqYeydgw+10DWdvOzLKv36pdKpfp8wVt6m5vCYZf0BeBXwD0RcbLxyxwRIanpN1DSTmAnwPr161tr7QKpHR/XLmrp7+8nyzLWrFnD9ddfz4YNG+rvLZVKDA8PMzAwMO1vaj3qZ58bz7Ks3om3cuVKNmzYwMUXX0yWZaxbt67eAZdlGRs2bGDVqlWcPn26fm7fnXNWVKGwS+qlGvTHI+LX+egjktZGxIfnq/cWEbuAXQBXXnll122SGsNZ27IuW7asfuHMjh07PneefWBggBUrVtSHS6XSeedfW8bq1atZsWIFEcGWLVs+d7FOb28vK1eu5NSpU9N6+M2KKNIbL+ARYF9E/KRhUq3e2/0kVu+ttpXu6+urn0tvh9ruOlDfM2imXC63bZmWjiJb9uuAbwFvSHo9H/dDqiF/Kq/9dgDYMS8tXOSaXbJa+zGYq8Z/hmnnfC1tRWq9/Ttwrm9Y0vXezvePMOfbdZ9pno2X47Zrvma+gq5F5+qlb3WevlDG2s1hb0HjP72cPb6VeQJtn6+Zw96iZr3h7fjXU9+DztrN521aNF/hazZfB91a4S17G3Qy8GZz5S27WSIcdrNEOOxmiXDYzRLhsJslwmE3S4TDbpYIh90sEQ67WSIcdrNEOOxmiXDYzRLhsJslwmE3S8SMYZe0TNJ/SvovSW9J+pt8/CZJuyW9K+lJSe27zaqZtV2RLfsZYHtEXAVsBW6SdC3wY+CnEfEl4ARw17y10sxaVqTWW0TEJ/lgb/4IYDvwdD4+6VpvZt2g0DG7pFJ+z/ijwIvAe8BYREzlbxmlWuyx2d/ulDQiaeT48eNtaLKZzUWhsEdEOSK2AkPANcAVRRcQEbsiYjgihgcHB+fWSjNr2ax64yNiDHgZ2AasllS7h90QcKi9TTOzdirSG/9FSavz1wPAjVRrtL8M3Ja/Lalab2bdqMjdZdcCj0kqUf1xeCoinpO0F3hC0t8Cr1Et/mhmi1SRWm//DVzdZPz7VI/fzawL+Ao6s0Q47GaJcNjNEuGwmyXCYTdLhMNulgiH3SwRDrtZIhx2s0Q47InLss++ApIWsCU23xz2hNWCnmVZPeiS6g9bWhz2hFUqlfpzRAAQEfWHLS1F/uutrWpfMFscasEul8v10JfL5WnDtjR0NOy1L5ItDo276pVKpb5uamH3ulpaOhp2SZRKpU4u0mYgadpue5ZllEql+sOWjo6GPcsyli9f3slF2gxqYa9tyUulEsuXL6e/v5/+/n6yLJu2K++Ou+7V8S17X59rSSwmzcLe399PX18fvb29DvcS0tGwj4+PMzIy0slFWkG1Y/Za2Ht7e9m3bx/j4+OUSqX6abrGDtbGc/S2+KmTva0XXHBBbNu2rWPLs+Iavwe18+7j4+McOXKE06dPA0w7hncv/eI0OjrKmTNnmu6OFQ57fsPJEeBQRNwsaRPwBHAR8ArwrYiYON88ent748ILL5xV463zat+JUqnEwMBAPeQO+OJ3vrDPZjf+bqq3kF6VD9dqvT0h6e+p1np76Hwz8DF7d2ncTXfQu1+hsEsaAv4U+BHwl6r22mwH/ix/y2PAXzND2LMsY2BgYM6Ntc7z1XRLR9Et+8+AHwAr8+GLmEWtN2AnQE9Pj8/ddoFaD3zjhTbW/WYMu6SbgaMR8Yqkr852ARGxC9gFsGzZsvCXx2xhFNmyXwfcIunrwDKqx+wPktd6y7fuhWq9RYSvjTdbIEUqwtwH3AeQb9m/HxHflPRLqrXenmAWtd4c9u7h8+hLSysX1fwVc6j15i+Q2cLo6EU1/f39MTQ01LHlmaXmfOfZvZk1S4TDbpYIh90sEQ67WSIcdrNEOOxmiXDYzRLhsJslwmE3S4TDbpYIh90sEQ67WSIcdrNEOOxmiXDYzRLhsJslwmE3S4TDbpYIh90sEUUrwnwAfAyUgamIGJY0CDwJbAQ+AHZExIn5aaaZtWo2W/brI2JrRAznw/cCL0XEZuClfNjMFqlWduNvpVrjjfz5Gy23xszmTdGwB/DPkl7Ja7cBXBIRH+avDwOXNPtDSTsljUgacYEIs4VTtEjEVyLikKTfA16UtL9xYkSEpKY3oG+s9dbf3+9yoGYLpNCWPSIO5c9Hgd8A1wBHJK0FyJ+Pzlcjzax1M4Zd0gpJK2uvgT8G3gSepVrjDWZR683MFkaR3fhLgN/kNbt7gH+KiBck7QGeknQXcADYMX/NNLNWFani+j5wVZPxvwNumI9GmVn7+Qo6s0Q47GaJcNjNEuGwmyXCYTdLhMNulgiH3SwRDrtZIhx2s0Q47GaJcNjNEuGwmyXCYTdLhMNulgiH3SwRDrtZIhx2s0Q47GaJKBR2SaslPS1pv6R9krZJGpT0oqR38ucL57uxZjZ3RbfsDwIvRMQVVO9Htw+XfzLrKkVuJX0B8EfAIwARMRERY7j8k1lXKbJl3wQcA34u6TVJD+f3jy9U/snMFociYe8Bvgw8FBFXA6c4a5c9IoJqPbjPca03s8WhSNhHgdGI2J0PP001/IXKP0XErogYjojhLHPnv9lCmTF9EXEYOCjp8nzUDcBeXP7JrKsUreL6F8DjkvqA94HvUP2hcPknsy5RKOwR8Tow3GSSyz+ZdQkfRJslwmE3S4TDbpYIh90sEQ67WSIcdrNEOOxmiXDYzRLhsJslwmE3S4TDbpYIh90sEQ67WSIcdrNEOOxmiXDYzRLhsJslwmE3S4TDbpaIIhVhLpf0esPjpKR7XOvNrLsUuZX02xGxNSK2An8AjAO/wbXezLrKbHfjbwDei4gDuNabWVeZbdhvB36Rv3atN7MuUjjseYGIW4Bfnj3Ntd7MFr/ZbNn/BHg1Io7kw671ZtZFZpO+O/hsFx5c682sqxQKe16P/Ubg1w2j7wdulPQO8LV82MwWqaK13k4BF5017ne41ptZ1/BBtFkiHHazRDjsZolw2M0S4bCbJcJhN0uEw26WCIfdLBEOu1kiHHazRDjsZolw2M0S4bCbJcJhN0uEw26WCIfdLBGq3iuyQwuTjgGngP/r2EI772L8+brVUvhsl0XEF5tN6GjYASSNRMRwRxfaQf583WspfzbwbrxZMhx2s0QsRNh3LcAyO8mfr3st5c/W+WN2M1sY3o03S0RHwy7pJklvS3pXUleXeJZ0qaSXJe2V9Jaku/PxS6puvaSSpNckPZcPb5K0O1+HT+Y1ALuSpNWSnpa0X9I+SduW2vpr1LGwSyoBf0e1ZtwW4A5JWzq1/HkwBXwvIrYA1wLfzT/PUqtbfzewr2H4x8BPI+JLwAngrgVpVXs8CLwQEVcAV1H9nEtt/X0mIjryALYBv20Yvg+4r1PL78Dne4Zqiay3gbX5uLXA2wvdthY+0xDVL/x24DlAVC866Wm2TrvpAVwA/C95v1XD+CWz/s5+dHI3fj1wsGF4NB/X9SRtBK4GdrO06tb/DPgBUKu1fREwFhFT+XA3r8NNwDHg5/lhysN5TcOltP6mcQddiyR9AfgVcE9EnGycFtXNQ1ee7pB0M3A0Il5Z6LbMkx7gy8BDEXE11cu4p+2yd/P6a6aTYT8EXNowPJSP61qSeqkG/fGIqFW4LVS3vgtcB9wi6QPgCaq78g8CqyXVCoJ28zocBUYjYnc+/DTV8C+V9fc5nQz7HmBz3pvbB9xOtcZ7V5Ik4BFgX0T8pGHSkqhbHxH3RcRQRGykuq7+JSK+CbwM3Ja/rZs/32HgoKTL81E3AHtZIuuvmU7/19vXqR4HloBHI+JHHVt4m0n6CvBvwBt8dkz7Q6rH7U8BG4ADwI6IOL4gjWwTSV8Fvh8RN0v6fapb+kHgNeDOiDizgM2bM0lbgYeBPuB94DtUN4BLav3V+Ao6s0S4g84sEQ67WSIcdrNEOOxmiXDYzRLhsJslwmE3S4TDbpaI/wehYJSNJBSMEAAAAABJRU5ErkJggg==\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "radii = [1,2] # radius of our toy nodule, but here we do not need it.\n",
    "spacing = (1.,1.) # spacing of 3d array\n",
    "rnd = np.random.random() / 2 + 0.75\n",
    "bw2, bws2, bwc2, bwr2 = scale(img=black_white, scale_factor=rnd, spacing=spacing, centers=centers, radii=radii)\n",
    "print('shape', bw2.shape)\n",
    "print(bws2, bwr2)\n",
    "plt.imshow(bw2, cmap=plt.cm.gray)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now, to show you the 3d example, I want to make an all zeros 3d image with just one 1.0 in it. This is a toy example, in contrast to the real problem, the voxel in which its value is 1.0 will point to the center of a \"possible nodule\". We made the array to track the place of our \"toy nodule\" after transformations!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(0.8449698472452225, 0.8449698472452225, 0.8449698472452225) [5]\n"
     ]
    }
   ],
   "source": [
    "img = np.zeros((100, 100, 100), dtype=float)\n",
    "centers = [(60, 60, 60)] # voxel which will be 1.0\n",
    "img[centers[0]] = 1.\n",
    "radii = [5] # radius of our toy nodule, but here we do not need it.\n",
    "spacing = (1.,1.,1.) # spacing of 3d array\n",
    "rnd = np.random.random() / 2 + 0.75\n",
    "img2, spacing2, centers2, radii2 = scale(img=img, scale_factor=rnd, spacing=spacing, centers=centers, radii=radii)\n",
    "print(spacing2, radii)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "So now we wonder if the resulting center is still the highest value of the resulting image or not. Let's see:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[(51, 51, 51)]\n",
      "((50, 50, 50), 0.4557698533434679)\n"
     ]
    }
   ],
   "source": [
    "print(centers2)\n",
    "print(argmax_3d(img2))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Yes! It is. but as you see, the max value is less than 1.0! why? It is because of the `scipy.ndimage.interpolation.zoom` method which we have chosen mode='nearest'. You can find documentation [here](https://docs.scipy.org/doc/scipy-0.14.0/reference/generated/scipy.ndimage.interpolation.zoom.html)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Random crop\n",
    "\n",
    "Random cropping is very important to avoid over-fitting. We must consider not cropping in a manner that nodule always stays in the center of 3d image, so this is why it is called \"random\" cropping.\n",
    "\n",
    "If we assume block_size as a constant, then we can assign each point inside of the original image exactly one cropping 3d cube.\n",
    "Then the procedure is simple, first, we should define a bounding box for the center of cropping 3d cube, then randomly choose one of the points inside that bounding box as a center, and then crop 3d image!\n",
    "\n",
    "Assume that the below picture is a ct scan which contains a nodule in it we want to randomly crop the image in a way that it contains nodule.\n",
    "![not cropped image](./figs/one_3d_cube.jpeg)\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "One of the cropping forms could be this one:\n",
    "![cropped image](./figs/two_3d_cubes.jpeg)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "def _get_cube_from_img_new(img, origin: tuple, block_size=128, pad_value=106.):\n",
    "    assert 2 <= len(origin) <= 3\n",
    "    final_image_shape = tuple([block_size] * len(origin))\n",
    "    result = np.ones(final_image_shape) * pad_value\n",
    "    start_at_original_images = []\n",
    "    end_at_original_images = []\n",
    "    start_at_result_images = []\n",
    "    end_at_result_images = []\n",
    "    for i, center_of_a_dim in enumerate(origin):\n",
    "        start_at_original_image = int(center_of_a_dim - block_size / 2)\n",
    "        end_at_original_image = start_at_original_image + block_size\n",
    "        if start_at_original_image < 0:\n",
    "            start_at_result_image = abs(start_at_original_image)\n",
    "            start_at_original_image = 0\n",
    "        else:\n",
    "            start_at_result_image = 0\n",
    "        if end_at_original_image > img.shape[i]:\n",
    "            end_at_original_image = img.shape[i]\n",
    "            end_at_result_image = start_at_result_image + (end_at_original_image - start_at_original_image)\n",
    "        else:\n",
    "            end_at_result_image = block_size\n",
    "        start_at_original_images.append(start_at_original_image)\n",
    "        end_at_original_images.append(end_at_original_image)\n",
    "        start_at_result_images.append(start_at_result_image)\n",
    "        end_at_result_images.append(end_at_result_image)\n",
    "    # for simplicity\n",
    "    sri = start_at_result_images\n",
    "    eri = end_at_result_images\n",
    "    soi = start_at_original_images\n",
    "    eoi = end_at_original_images\n",
    "    if len(origin) == 3:\n",
    "        result[sri[0]:eri[0], sri[1]:eri[1], sri[2]:eri[2]] = img[soi[0]:eoi[0], soi[1]:eoi[1], soi[2]:eoi[2]]\n",
    "    elif len(origin) == 2:\n",
    "        result[sri[0]:eri[0], sri[1]:eri[1]] = img[soi[0]:eoi[0], soi[1]:eoi[1]]\n",
    "    return result\n",
    "\n",
    "def random_crop(img: np.array, centers: list, radii: list, main_nodule_idx: int, spacing: tuple, block_size: int,\n",
    "                pad_value: float, margin: int):\n",
    "    max_radius_index = np.max(np.round(radii[main_nodule_idx] / np.array(spacing)).astype(int))\n",
    "    center_of_cube = list(centers[main_nodule_idx])\n",
    "    shifts = []\n",
    "    for i in range(len(centers[main_nodule_idx])):\n",
    "        high = int(block_size / 2) - max_radius_index - margin\n",
    "        if high < 0:\n",
    "            raise ValueError('Image can not be cropped with this margin! (decrease it)')\n",
    "        shift = np.random.randint(low=-abs(high), high=abs(high))\n",
    "        center_of_cube[i] += shift\n",
    "        shifts.append(shift)    \n",
    "    out_img = _get_cube_from_img_new(img, origin=tuple(center_of_cube), block_size=block_size, pad_value=pad_value)\n",
    "    out_centers = []\n",
    "    for i in range(len(centers)):\n",
    "        diff = np.array(centers[main_nodule_idx]) - np.array(centers[i])\n",
    "        out_centers.append(\n",
    "            tuple(np.array([int(block_size / 2)] * len(centers[i]), dtype=int) - np.array(shifts, dtype=int) - diff))\n",
    "    return out_img, out_centers\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Like what we did previously, let's create a black and white image again."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "original image:\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "cropped image:\n",
      "new nodule centers: [(54, 49), (54, 59)]\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "black_white = np.zeros((200,200))\n",
    "centers = [(25,25), (25,35)]\n",
    "for i in range(50):\n",
    "    black_white[i, 0:50] = np.ones(50)\n",
    "\n",
    "# creating fake nodule\n",
    "for center in centers:\n",
    "    for i in [-1,0,1]:\n",
    "        for j in [-1,0,1]:\n",
    "            black_white[center[0] + i, center[1] + j] = 0.\n",
    "print('original image:')\n",
    "plt.imshow(black_white, cmap=plt.cm.gray)\n",
    "plt.show()\n",
    "out_img, out_centers = random_crop(black_white, centers=centers, radii=[1.,2.], main_nodule_idx=0, spacing=(1.,1.), block_size=100, pad_value=0, margin=10)\n",
    "print('cropped image:')\n",
    "print('new nodule centers:', out_centers)\n",
    "plt.imshow(out_img, cmap=plt.cm.gray)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now just like previous step, we want to test if it works for 3d image?"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "new parameters are: main_nodule_idx, pad_value, block_size, margin\n",
    "\n",
    "* **main_nodule_idx**: we are passing all existing nodules at ct scan by `centers` and `radii` parameter. `centers` is a list which points to the center of nodules and `radii` is the list of radiuses for corresponding centers. With main_nodule_idx we specify which nodule MUST be inside the patch (also some others \"may\" be inside it). main_nodule_idx is an integer and is the index of the main nodule in the `radii` and `centers` list.\n",
    "* **pad_value**: if a patch falls out of the original image, it will be filled with pad_value.\n",
    "* **block_size**: size of the patch in each axis. (at the paper which we are going through it, block_size is 128 which means resulting patches are 128\\*128\\*128)\n",
    "* **margin**: it is the margin that we don't want a nodule to be inside that area. if we set big a margin, it means that we want patches that their main nodule is near the center of the patch."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "img = np.zeros((100, 100, 100), dtype=float)\n",
    "centers = [(60, 60, 60)] # voxel which will be 1.0\n",
    "img[centers[0]] = 1.\n",
    "radii = [5] # radius of our toy nodule, but here we do not need it.\n",
    "spacing = (1.,1.,1.) # spacing of 3d array\n",
    "rnd = np.random.random() / 2 + 0.75\n",
    "img3, centers3 = random_crop(img=img, centers=centers, radii=radii, main_nodule_idx=0, spacing=spacing, block_size=30, pad_value=0.0, margin=5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "((12, 11, 19), 1.0)\n",
      "(12, 11, 19)\n"
     ]
    }
   ],
   "source": [
    "print(argmax_3d(img3))\n",
    "print(centers3[0])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Yes!\n",
    "\n",
    "Now I want to add another center to the original image. Lets test two scenarios:\n",
    "* The second center is inside the cropped image\n",
    "* The second center is NOT inside the cropped image"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### The second center is inside the cropped image\n",
    "\n",
    "I add the center of the next nodule with (56,56,56) which its distance to the first one is (4,4,4). so if I set the margin 5, it means that the second nodule will always be inside the marginal distance to the first nodule (because (4,4,4) < (5,5,5)), so random cropping will never cut out the second nodule and will always exist on the resulting patch."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[(24, 20, 13), (20, 16, 9)]\n",
      "[1.0, 1.0]\n"
     ]
    }
   ],
   "source": [
    "img = np.zeros((100, 100, 100), dtype=float)\n",
    "centers = [(60, 60, 60), (56,56,56)]\n",
    "# stands for radiuses of nodules, but here we do not need it.\n",
    "radii = [1, 2]\n",
    "spacing = (1.,1.,1.)\n",
    "img[centers[0]] = 1.\n",
    "img[centers[1]] = 1.\n",
    "img3, centers3 = random_crop(img=img, centers=centers, radii=radii, main_nodule_idx=0, spacing=spacing, block_size=30, pad_value=0.0,margin=5)\n",
    "print(centers3)\n",
    "print([img3[centers3[0]], img3[centers3[1]]])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### The second center is NOT inside the cropped image\n",
    "Now I added second nodules center with a distance of (31,31,31) which is bigger than block_size! Meaning that it will always fall out of the resulting patch!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[(15, 17, 9), (46, 48, 40)]\n"
     ]
    },
    {
     "ename": "IndexError",
     "evalue": "index 46 is out of bounds for axis 0 with size 30",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mIndexError\u001b[0m                                Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-13-744b1a479085>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m      8\u001b[0m \u001b[0mimg3\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcenters3\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mrandom_crop\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mimg\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mimg\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcenters\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mcenters\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mradii\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mradii\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mmain_nodule_idx\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mspacing\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mspacing\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mblock_size\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m30\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mpad_value\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m0.0\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mmargin\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      9\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mcenters3\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 10\u001b[0;31m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mimg3\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mcenters3\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mimg3\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mcenters3\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;31mIndexError\u001b[0m: index 46 is out of bounds for axis 0 with size 30"
     ]
    }
   ],
   "source": [
    "img = np.zeros((100, 100, 100), dtype=float)\n",
    "centers = [(60, 60, 60), (91,91,91)]\n",
    "# stands for radiuses of nodules, but here we do not need it.\n",
    "radii = [5, 6]\n",
    "spacing = (1.,1.,1.)\n",
    "img[centers[0]] = 1.\n",
    "img[centers[1]] = 1.\n",
    "img3, centers3 = random_crop(img=img, centers=centers, radii=radii, main_nodule_idx=0, spacing=spacing, block_size=30, pad_value=0.0,margin=1)\n",
    "print(centers3)\n",
    "print([img3[centers3[0]], img3[centers3[1]]])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "As you can see, the second nodule is not inside of the cropped 3d patch. <b>because we had mentioned that `main_nodule_idx=0`</b>, we could change it to 1, then the first nodule would not be in the patch! "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Random rotation\n",
    "\n",
    "Now, we have some patches with the size of (block_size\\*block_size\\*block_size), we can randomly rotate it. But we should consider that if we rotate the 3d patch, `centers` of the nodules, as well as `spacing` of 3d array, may be affected.\n",
    "(It is obvious that why centers change, but why spacing changes? because if we rotate a 3d array, then the resulting array's sort of axes may not be the same as the original one. for example, if we rotate a 3d array with axes sort of z,y,x 90 degrees, it may change the axes sort to y,z,x. so the spacing of z may not be the same as the spacing for y and we should change the spacing orders too!)\n",
    "\n",
    "**note1:** All of our rotations are 90 degrees.\n",
    "\n",
    "**note2:** Again! I have written the rotation method for both 2d and 3d usages. Here I show 2d version, But the 3d one works very similarly. (Try it!)\n",
    "\n",
    "new parameter: rot_id\n",
    "* rot_id: it is sth that I assigned to each rotation. for example in 2d, rot_id=3 means 3 * 90 degrees of rotation. if rot_id >= 4, it will flip with respect to y-axis."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "from functools import partial\n",
    "\n",
    "def _get_point_after_2d_rotation(in_points: list, shape: tuple, rot90s: int, flip: bool = False):\n",
    "    assert len(in_points[0]) == 2 and len(shape) == 2\n",
    "    rot90s = rot90s % 4\n",
    "    result_points = []\n",
    "    for in_point in in_points:\n",
    "        result_point = list(in_point)\n",
    "        for i in range(rot90s):\n",
    "            previous = result_point.copy()\n",
    "            axes = [0, 1]\n",
    "            point_complement = (shape[0] - previous[0], shape[1] - previous[1])\n",
    "            result_point[axes[0]] = point_complement[axes[1]]\n",
    "            result_point[axes[1]] = previous[axes[0]]\n",
    "        if flip:\n",
    "            result_point[0] = shape[0] - result_point[0]\n",
    "        result_points.append(tuple(result_point))\n",
    "    return result_points\n",
    "\n",
    "\n",
    "def _get_point_after_3d_rotation(in_points: list, shape: tuple, axes, rot90s: int, flip: bool = False):\n",
    "    rot90s = rot90s % 4\n",
    "    result_points = []\n",
    "    for in_point in in_points:\n",
    "        result_point = list(in_point)\n",
    "        other_axis = [item for item in [0, 1, 2] if item not in axes]\n",
    "        for i in range(rot90s):\n",
    "            previous = result_point.copy()\n",
    "            point_complement = np.array(shape, dtype=int) - np.array(previous, dtype=int)\n",
    "            result_point[axes[0]] = point_complement[axes[1]]\n",
    "            result_point[axes[1]] = previous[axes[0]]\n",
    "        if flip:\n",
    "            result_point[other_axis[0]] = shape[other_axis[0]] - result_point[other_axis[0]]\n",
    "        result_points.append(tuple(result_point))\n",
    "    return result_points\n",
    "\n",
    "\n",
    "def rotate(img: np.array, spacing: tuple, centers: list, rotate_id: int):\n",
    "    spacing = list(spacing)\n",
    "    dimensions = len(img.shape)\n",
    "    assert (dimensions == 3 and rotate_id < 24) or (dimensions == 2 and rotate_id < 8)\n",
    "    other_axes = [i for i in range(dimensions)]\n",
    "\n",
    "    if dimensions == 2:\n",
    "        axis = [0]\n",
    "        out_centers = partial(_get_point_after_2d_rotation, in_points=centers, shape=tuple(img.shape))\n",
    "    else:  # dimensions == 3\n",
    "        axis = rotate_id // 8\n",
    "        other_axes.pop(axis)\n",
    "        out_centers = partial(_get_point_after_3d_rotation, in_points=centers, shape=tuple(img.shape), axes=other_axes)\n",
    "\n",
    "    which_rotation = rotate_id % 8\n",
    "    flip = which_rotation >= 4\n",
    "    rotation_times = (which_rotation % 4)\n",
    "\n",
    "    spacing_exchanged = (which_rotation % 2) != 0\n",
    "    if spacing_exchanged:\n",
    "        if dimensions == 3:\n",
    "            tmp = spacing[other_axes[0]]\n",
    "            spacing[other_axes[0]] = spacing[other_axes[1]]\n",
    "            spacing[other_axes[1]] = tmp\n",
    "        elif dimensions == 2:\n",
    "            tmp = spacing[0]\n",
    "            spacing[0] = spacing[1]\n",
    "            spacing[1] = tmp\n",
    "    img = np.rot90(img, k=rotation_times, axes=other_axes)\n",
    "    if flip:\n",
    "        img = np.flip(img, axis=axis)\n",
    "    return img, tuple(spacing), out_centers(rot90s=rotation_times, flip=flip)\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [],
   "source": [
    "black_white = np.zeros((200,200))\n",
    "centers = [(25,25), (25,35)]\n",
    "for i in range(50):\n",
    "    black_white[i, 0:50] = np.ones(50)\n",
    "\n",
    "# creating fake nodule\n",
    "for center in centers:\n",
    "    for i in [-1,0,1]:\n",
    "        for j in [-1,0,1]:\n",
    "            black_white[center[0] + i, center[1] + j] = 0."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "from matplotlib import pyplot as plt\n",
    "plt.imshow(black_white, cmap=plt.cm.bone)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(1.0, 2.0) [(25, 25), (25, 35)]\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(2.0, 1.0) [(175, 25), (165, 25)]\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAQEAAAD8CAYAAAB3lxGOAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy86wFpkAAAACXBIWXMAAAsTAAALEwEAmpwYAAANy0lEQVR4nO3df6zddX3H8efLgpgwE2DUSqAM1GoiZumgQZYJovMHkmWF/cHKllGVrLDQzC0kC7pkkhmXZZORmCmmRkJNJsgkKCNMrcToPxZpseGXIAVLaFdaBQJummLLe3+c79Xj7b203HO+99zez/ORnJzv93N+fN8fzu0r3+/5Hr7vVBWS2vWqSRcgabIMAalxhoDUOENAapwhIDXOEJAa11sIJLkgyaNJtie5pq/tSBpN+vidQJIlwI+A9wI7gXuBS6vq4bFvTNJI+toTOBvYXlVPVNWLwC3A6p62JWkER/X0vicDTw2t7wTePtuTk/izRal/P62qpdMH+wqBQ0qyDlg3qe1LDXpypsG+QmAXsHxo/ZRu7FeqagOwAdwTkCapr+8E7gVWJDk9yauBNcAdPW1L0gh62ROoqv1J1gPfAJYAN1bVQ31sS9JoejlF+IqL8HBAmg9bq2rV9EF/MSg1zhCQGmcISI0zBKTGGQJS4wwBqXGGgNQ4Q0BqnCEgNc4QkBpnCEiNMwSkxhkCUuMMAalxhoDUOENAapwhIDXOEJAaN+cQSLI8ybeTPJzkoSQf6cavTbIrybbuduH4ypU0bqNcaHQ/cHVV3ZfktcDWJJu6x66vqk+NXp6kvs05BKpqN7C7W/5Zkh8y6Dwk6Qgylu8EkpwG/B5wTze0Psn9SW5Mcvw4tiGpHyOHQJLfAm4D/qaqXgBuAN4IrGSwp3DdLK9bl2RLki2j1iBp7kbqO5DkaOBO4BtV9W8zPH4acGdVve0Q72PfAal/4+07kCTAF4AfDgdAkpOGnnYx8OBctyGpf6OcHfgD4C+AB5Js68Y+BlyaZCVQwA7gihG2IalntiGT2mEbMkkHMwSkxhkCUuMMAalxhoDUOENAapwhIDXOEJAaZwhIjTMEpMYZAlLjDAGpcYaA1DhDQGqcISA1zhCQGmcISI0zBKTGGQJS40a50CgASXYAPwMOAPuralWSE4AvA6cxuNjoJVX13KjbkjR+49oTeFdVrRy6iOE1wN1VtQK4u1uXtAD1dTiwGtjYLW8ELuppO5JGNI4QKOCbSbYmWdeNLesalgI8DSyb/iLbkEkLw8jfCQDvqKpdSV4HbEryyPCDVVUz9RWoqg3ABrDvgDRJI+8JVNWu7n4vcDtwNrBnqh1Zd7931O1I6sdIIZDk2CSvnVoG3seg9+AdwNruaWuBr42yHUn9GfVwYBlw+6A3KUcBX6qqrye5F7g1yeXAk8AlI25HUk/sRSi1w16Ekg5mCEiNMwSkxhkCUuMMAalxhoDUOENAapwhIDXOEJAaZwhIjTMEpMYZAlLjDAGpcYaA1DhDQGqcISA1zhCQGmcISI2b8zUGk7yFQauxKW8A/gE4DvhL4Cfd+Meq6q65bkdSv8ZyjcEkS4BdwNuBDwH/W1WfegWv9xqDUv96vcbgHwKPV9WTY3o/SfNkXCGwBrh5aH19kvuT3Jjk+JleYBsyaWEY+XAgyauB/wHOqKo9SZYBP2XQo/ATwElV9eFDvIeHA1L/ejsc+ABwX1XtAaiqPVV1oKpeAj7PoC2ZpAVqHCFwKUOHAlM9CDsXM2hLJmmBGqkNWdd/8L3AFUPD/5JkJYPDgR3THpO0wNiGTGqHbcgkHcwQkBpnCEiNMwSkxhkCUuMMAalxhoDUOENAapwhIDXOEJAaZwhIjTMEpMYZAlLjDAGpcYaA1DhDQGqcISA1zhCQGndYIdD1D9ib5MGhsROSbEryWHd/fDeeJJ9Osr3rPXBmX8VLGt3h7gncBFwwbewa4O6qWgHc3a3D4BLkK7rbOuCG0cuU1JfDCoGq+i7w7LTh1cDGbnkjcNHQ+BdrYDNw3LTLkEtaQEb5TmBZVe3ulp8GlnXLJwNPDT1vZzcmaQEaqe/AlKqqV3rZ8CTrGBwuSJqgUfYE9kzt5nf3e7vxXcDyoeed0o39hqraUFWrZroOuqT5M0oI3AGs7ZbXAl8bGr+sO0twDvD80GGDpIWmqg55Y9BrcDfwSwbH+JcDv83grMBjwLeAE7rnBvgM8DjwALDqMN6/vHnz1vtty0z//mxDJrXDNmSSDmYISI0zBKTGGQJS4wwBqXGGgNQ4Q0BqnCEgNc4QkBpnCEiNMwSkxhkCUuMMAalxhoDUOENAapwhIDXOEJAaZwhIjTtkCMzSguxfkzzStRm7Pclx3fhpSX6RZFt3+1yPtUsag8PZE7iJg1uQbQLeVlW/C/wI+OjQY49X1cruduV4ypTUl0OGwEwtyKrqm1W1v1vdzKC3gKQj0Di+E/gw8N9D66cn+UGS7yQ5dwzvL6lHI7UhS/L3wH7gP7qh3cCpVfVMkrOAryY5o6pemOG1tiGTFoA57wkk+SDwR8Cf11QHkap9VfVMt7yVQQOSN8/0etuQSQvDnEIgyQXA3wF/XFU/HxpfmmRJt/wGYAXwxDgKldSPQx4OJLkZOB84MclO4OMMzgYcA2xKArC5OxNwHvCPSX4JvARcWVXPzvjGkhYE25BJ7bANmaSDGQJS4wwBqXGGgNQ4Q0BqnCEgNc4QkBpnCEiNMwSkxhkCUuMMAalxhoDUOENAapwhIDXOEJAaZwhIjTMEpMYZAlLj5tqG7Noku4bajV049NhHk2xP8miS9/dVuKTxmGsbMoDrh9qN3QWQ5K3AGuCM7jWfnbr6sKSFaU5tyF7GauCWrv/Aj4HtwNkj1CepZ6N0IFqf5DJgC3B1VT0HnMygN+GUnd3Yy3rdScv5s8uvHqGUhel7m77FPffcOekypJc11xC4AfgEUN39dQx6Eh624TZkp556Ktd/4iNzLGXh+siBlwwBLXhzOjtQVXuq6kBVvQR8nl/v8u8Clg899ZRubKb3+FUbsqVLl86lDEljMNc2ZCcNrV4MTJ05uANYk+SYJKczaEP2/dFKlNSnubYhOz/JSgaHAzuAKwCq6qEktwIPM+hWfFVVHeilckljccgQqKpLZxj+wss8/5PAJ0cpStL88ReDUuMMAalxhoDUOENAapwhIDXOEJAaZwhIjTMEpMaN8n8RHnG+vHkzL774SwDOefMKVrz+9ROuSJq8pvYE/urCi7nsnedx2TvP4yv/9e1JlyMtCE2FgKSDNXU4cPTRx3D00ccAsOQor3omQWMhsGfPjkmXIC04Hg5IjTMEpMYZAlLjDAGpcYaA1Li5tiH78lALsh1JtnXjpyX5xdBjn+uxdkljcDinCG8C/h344tRAVf3p1HKS64Dnh57/eFWtHFN9Y/Wpjf/Jvl/sA+Dd7zmH33/TmyZckTR5h3Oh0e8mOW2mx5IEuAR495jr6sU//e1f89xzTw+WN3zJEJAY/TuBc4E9VfXY0NjpSX6Q5DtJzh3x/SX1bNRfDF4K3Dy0vhs4taqeSXIW8NUkZ1TVC9NfOL0N2Xw44YSTeNWrBrn3mmNfMy/blBa6OYdAkqOAPwHOmhqrqn3Avm55a5LHgTczaFr6G6pqA7ABYNWqVTXXOl6J7dvvm4/NSEeUUQ4H3gM8UlU7pwaSLE2ypFt+A4M2ZE+MVqKkPh3OKcKbge8Bb0myM8nl3UNr+M1DAYDzgPu7U4ZfAa6sqmfHWK+kMZtrGzKq6oMzjN0G3DZ6WZLmi78YlBpnCEiNMwSkxhkCUuMMAalxhoDUOENAapwhIDXOEJAaZwhIjTMEpMYZAlLjDAGpcYaA1DhDQGqcISA1zhCQGmcISI0zBKTGGQJS4wwBqXGGgNS4VM1L85+XLyL5CfB/wE8nXUsPTmRxzgsW79wW67x+p6qWTh9cECEAkGRLVa2adB3jtljnBYt3bot1XrPxcEBqnCEgNW4hhcCGSRfQk8U6L1i8c1us85rRgvlOQNJkLKQ9AUkTMPEQSHJBkkeTbE9yzaTrGVWSHUkeSLItyZZu7IQkm5I81t0fP+k6DyXJjUn2JnlwaGzGeWTg091neH+SMydX+aHNMrdrk+zqPrdtSS4ceuyj3dweTfL+yVTdn4mGQJIlwGeADwBvBS5N8tZJ1jQm76qqlUOnma4B7q6qFcDd3fpCdxNwwbSx2ebxAWBFd1sH3DBPNc7VTRw8N4Dru89tZVXdBdD9Pa4Bzuhe89nu73bRmPSewNnA9qp6oqpeBG4BVk+4pj6sBjZ2yxuBiyZXyuGpqu8Cz04bnm0eq4Ev1sBm4LgkJ81LoXMwy9xmsxq4par2VdWPge0M/m4XjUmHwMnAU0PrO7uxI1kB30yyNcm6bmxZVe3ulp8Glk2mtJHNNo/F8jmu7w5nbhw6ZFssc5vVpENgMXpHVZ3JYBf5qiTnDT9Yg9MxR/wpmcUyjyE3AG8EVgK7gesmWs08mnQI7AKWD62f0o0dsapqV3e/F7idwa7jnqnd4+5+7+QqHMls8zjiP8eq2lNVB6rqJeDz/HqX/4if26FMOgTuBVYkOT3Jqxl8AXPHhGuasyTHJnnt1DLwPuBBBnNa2z1tLfC1yVQ4stnmcQdwWXeW4Bzg+aHDhiPCtO8wLmbwucFgbmuSHJPkdAZffn5/vuvr01GT3HhV7U+yHvgGsAS4saoemmRNI1oG3J4EBv9tv1RVX09yL3BrksuBJ4FLJljjYUlyM3A+cGKSncDHgX9m5nncBVzI4EuznwMfmveCX4FZ5nZ+kpUMDnF2AFcAVNVDSW4FHgb2A1dV1YEJlN0bfzEoNW7ShwOSJswQkBpnCEiNMwSkxhkCUuMMAalxhoDUOENAatz/AxZpBNBF8Hp0AAAAAElFTkSuQmCC\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(1.0, 2.0) [(175, 175), (175, 165)]\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAQEAAAD8CAYAAAB3lxGOAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy86wFpkAAAACXBIWXMAAAsTAAALEwEAmpwYAAANnUlEQVR4nO3df+hd9X3H8eer8dfWCsYfC1bt1JIVtIzMBiusijLbqoxGYbiEMdNWGgWFCsLQbqwyJ4ytzlLWKpEGla1aqViluKoLnf6x2Rpb8Ve1iTZisphULdqtpW30vT/u+drbb77fJH7vPbnffD/PBxzuOZ977jmfT+43L86Py3mnqpDUrndNugOSJssQkBpnCEiNMwSkxhkCUuMMAalxvYVAknOSPJdkU5Kr+tqPpNGkj98JJFkE/Aj4KLAFeBRYVVXPjH1nkkbS15HAqcCmqnqhqn4F3AGs6GlfkkZwQE/bPQZ4aWh5C/Dh2VZO4s8Wpf69UlVHTW/sKwT2KMkaYM2k9i816MWZGvsKga3AcUPLx3Ztb6uqtcBa8EhAmqS+rgk8CixNckKSg4CVwL097UvSCHo5EqiqnUkuB+4HFgHrqurpPvYlaTS93CJ8x53wdEDaFx6rquXTG/3FoNQ4Q0BqnCEgNc4QkBpnCEiNMwSkxhkCUuMMAalxhoDUOENAapwhIDXOEJAaZwhIjTMEpMYZAlLjDAGpcYaA1DhDQGrcnEMgyXFJvpPkmSRPJ/ls135Nkq1JHu+m88bXXUnjNsqDRncCV1bV95McCjyW5MHuvRuq6gujd09S3+YcAlW1DdjWzf8syQ8ZVB6StB8ZyzWBJMcDfwR8t2u6PMkTSdYlWTyOfUjqx8ghkOQ9wF3AFVX1BnAj8H5gGYMjhetn+dyaJBuSbBi1D5LmbqS6A0kOBL4F3F9V/zzD+8cD36qqD+5hO9YdkPo33roDSQJ8FfjhcAAkOXpotQuAp+a6D0n9G+XuwB8Dfwk8meTxru1zwKoky4ACNgOXjLAPST2zDJnUDsuQSdqVISA1zhCQGmcISI0zBKTGGQJS4wwBqXGGgNQ4Q0BqnCEgNc4QkBpnCEiNMwSkxhkCUuMMAalxhoDUOENAapwhIDXOEJAaN8qDRgFIshn4GfAmsLOqlic5HPg6cDyDh41eWFU/HXVfksZvXEcCZ1XVsqGHGF4FrK+qpcD6blnSPNTX6cAK4NZu/lbg/J72I2lE4wiBAh5I8liSNV3bkq5gKcDLwJLpH7IMmTQ/jHxNAPhIVW1N8nvAg0meHX6zqmqmugJVtRZYC9YdkCZp5COBqtrave4A7gZOBbZPlSPrXneMuh9J/RgpBJK8O8mhU/PAxxjUHrwXWN2tthq4Z5T9SOrPqKcDS4C7B7VJOQD4WlV9O8mjwJ1JLgZeBC4ccT+SemItQqkd1iKUtCtDQGqcISA1zhCQGmcISI0zBKTGGQJS4wwBqXGGgNQ4Q0BqnCEgNc4QkBpnCEiNMwSkxhkCUuMMAalxhoDUOENAatycnzGY5AMMSo1NORH4W+Aw4DPAT7r2z1XVfXPdj6R+jeUZg0kWAVuBDwOfAv63qr7wDj7vMwal/vX6jME/AZ6vqhfHtD1J+8i4QmAlcPvQ8uVJnkiyLsnimT5gGTJpfhj5dCDJQcD/ACdX1fYkS4BXGNQovBY4uqo+vYdteDog9a+304Fzge9X1XaAqtpeVW9W1VvAzQzKkkmap8YRAqsYOhWYqkHYuYBBWTJJ89RIZci6+oMfBS4Zav7HJMsYnA5snvaepHnGMmRSOyxDJmlXhoDUOENAapwhIDXOEJAaZwhIjTMEpMYZAlLjDAGpcYaA1DhDQGqcISA1zhCQGmcISI0zBKTGGQJS4wwBqXGGgNS4vQqBrn7AjiRPDbUdnuTBJBu718Vde5J8KcmmrvbAKX11XtLo9vZI4BbgnGltVwHrq2opsL5bhsEjyJd20xrgxtG7KakvexUCVfUw8Nq05hXArd38rcD5Q+231cAjwGHTHkMuaR4Z5ZrAkqra1s2/DCzp5o8BXhpab0vXJmkeGqnuwJSqqnf62PAkaxicLkiaoFGOBLZPHeZ3rzu69q3AcUPrHdu1/ZaqWltVy2d6DrqkfWeUELgXWN3NrwbuGWq/qLtLcBrw+tBpg6T5pqr2ODGoNbgN+DWDc/yLgSMY3BXYCPwHcHi3boAvA88DTwLL92L75eTk1Pu0Yab/f5Yhk9phGTJJuzIEpMYZAlLjDAGpcYaA1DhDQGqcISA1zhCQGmcISI0zBKTGGQJS4wwBqXGGgNQ4Q0BqnCEgNc4QkBpnCEiNMwSkxu0xBGYpQfZPSZ7tyozdneSwrv34JL9I8ng33dRj3yWNwd4cCdzCriXIHgQ+WFV/CPwIuHroveeralk3XTqebkrqyx5DYKYSZFX1QFXt7BYfYVBbQNJ+aBzXBD4N/PvQ8glJfpDkoSSnj2H7kno0UhmyJH8N7AT+rWvaBryvql5N8iHgm0lOrqo3ZvisZcikeWDORwJJPgn8KfAXNVVBpOqXVfVqN/8YgwIkfzDT5y1DJs0PcwqBJOcAfwV8oqp+PtR+VJJF3fyJwFLghXF0VFI/9ng6kOR24EzgyCRbgM8zuBtwMPBgEoBHujsBZwB/l+TXwFvApVX12owbljQvWIZMaodlyCTtyhCQGmcISI0zBKTGGQJS4wwBqXGGgNQ4Q0BqnCEgNc4QkBpnCEiNMwSkxhkCUuMMAalxhoDUOENAapwhIDXOEJAaN9cyZNck2TpUbuy8ofeuTrIpyXNJPt5XxyWNx1zLkAHcMFRu7D6AJCcBK4GTu898Zerpw5LmpzmVIduNFcAdXf2BHwObgFNH6J+kno1SgejyJBcBG4Arq+qnwDEMahNO2dK1SfuF005bwWlnnzXpbvTii39/xYztcw2BG4Frgeper2dQk3CvWYZM89FpZ5/FDdd+dtLd6MVsITCnuwNVtb2q3qyqt4Cb+c0h/1bguKFVj+3aZtqGZcikeWCuZciOHlq8AJi6c3AvsDLJwUlOYFCG7HujdVFSn+ZahuzMJMsYnA5sBi4BqKqnk9wJPMOgWvFlVfVmLz2XNBZ7DIGqWjVD81d3s/51wHWjdErSvuMvBqXGGQJS4wwBqXGGgNQ4Q0BqnCEgNc4QkBpnCEiNMwSkxhkCUuMMAalxhoDUOENAapwhIDXOEJAaZwhIjTMEpMYZAlLj5lqG7OtDJcg2J3m8az8+yS+G3rupx75LGoO9qTtwC/AvwG1TDVX151PzSa4HXh9a//mqWjam/kn7hee2beMb96wH4F2LFnH1Z2Z6NOfAf23cyHfWfxeAQ373EK686M/2SR9nVVV7nIDjgadmaA/wErB0d+vtxfbLyWk+TFf8zRdrLm576OG3t3HggQfvdt3rbvrXt9c94oj3zml/cwFsqBn+/416TeB0YHtVbRxqOyHJD5I8lOT0EbcvqWej1CIEWAXcPrS8DXhfVb2a5EPAN5OcXFVvTP+gZci0kBxy8EEcccR7ATjwwEN2v+57fuftdRcvPnq36+4TMx0eTJ+Y4TCfQYBsB47dzef+E1i+F9uf+GGgkxPM/XRgf0APpwNnA89W1ZaphiRHJVnUzZ/IoAzZCyPsQ1LP9uYW4e3AfwMfSLIlycXdWyv57VMBgDOAJ7pbht8ALq2q18bYX0ljNtcyZFTVJ2douwu4a/RuSdpX/MWg1DhDQGqcISA1zhCQGmcISI0zBKTGGQJS4wwBqXGGgNQ4Q0BqnCEgNc4QkBpnCEiNMwSkxhkCUuMMAalxhoDUOENAapwhIDXOEJAaZwhIjTMEpMZlUJhkwp1IfgL8H/DKpPvSgyNZmOOChTu2hTqu36+qo6Y3zosQAEiyoaqWT7of47ZQxwULd2wLdVyz8XRAapwhIDVuPoXA2kl3oCcLdVywcMe2UMc1o3lzTUDSZMynIwFJEzDxEEhyTpLnkmxKctWk+zOqJJuTPJnk8SQburbDkzyYZGP3unjS/dyTJOuS7Ejy1FDbjOPIwJe67/CJJKdMrud7NsvYrkmytfveHk9y3tB7V3djey7JxyfT6/5MNASSLAK+DJwLnASsSnLSJPs0JmdV1bKh20xXAeuraimwvlue724BzpnWNts4zgWWdtMa4MZ91Me5uoVdxwZwQ/e9Lauq+wC6v8eVwMndZ77S/d0uGJM+EjgV2FRVL1TVr4A7gBUT7lMfVgC3dvO3AudPrit7p6oeBl6b1jzbOFYAt9XAI8BhSY7eJx2dg1nGNpsVwB1V9cuq+jGwicHf7YIx6RA4BnhpaHlL17Y/K+CBJI8lWdO1Lamqbd38y8CSyXRtZLONY6F8j5d3pzPrhk7ZFsrYZjXpEFiIPlJVpzA4RL4syRnDb9bgdsx+f0tmoYxjyI3A+4FlwDbg+on2Zh+adAhsBY4bWj62a9tvVdXW7nUHcDeDQ8ftU4fH3euOyfVwJLONY7//Hqtqe1W9WVVvATfzm0P+/X5sezLpEHgUWJrkhCQHMbgAc++E+zRnSd6d5NCpeeBjwFMMxrS6W201cM9kejiy2cZxL3BRd5fgNOD1odOG/cK0axgXMPjeYDC2lUkOTnICg4uf39vX/evTAZPceVXtTHI5cD+wCFhXVU9Psk8jWgLcnQQG/7Zfq6pvJ3kUuDPJxcCLwIUT7ONeSXI7cCZwZJItwOeBf2DmcdwHnMfgotnPgU/t8w6/A7OM7cwkyxic4mwGLgGoqqeT3Ak8A+wELquqNyfQ7d74i0GpcZM+HZA0YYaA1DhDQGqcISA1zhCQGmcISI0zBKTGGQJS4/4fATx+LsLm42oAAAAASUVORK5CYII=\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(2.0, 1.0) [(25, 175), (35, 175)]\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAQEAAAD8CAYAAAB3lxGOAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy86wFpkAAAACXBIWXMAAAsTAAALEwEAmpwYAAANwElEQVR4nO3dbYxc5XnG8f9V8xKJIoELOC44xYATCaLKBQSRGiLSvAGqaugHalo1NEFdkECiUqQWUqlBzZeoDUWKmpBCa0HUhBc1JaCKJnFQG9QqNNgE8RYIBoywa+wCBtIkhdjc/TBnycTejc2emZ31Pv+fNJpznjMz536Y5dI5Z8Zzp6qQ1K5fmnQBkibLEJAaZwhIjTMEpMYZAlLjDAGpcWMLgSTnJHkiyaYkV41rP5L6yTi+J5BkCfAD4EPAFuB+4KKqemzkO5PUy7iOBM4ANlXV01X1OnArsGZM+5LUw0Fjet1jgeeG1rcAZ8724CR+bVELwjHLV7DiV4+ZdBljsXHjxheq6ug9x8cVAvuUZAqYmtT+pZn8/iWf4LpPXznpMsYiybMzjY8rBLYCK4bWj+vG3lRVNwA3dMV5JCBNyLiuCdwPrEqyMskhwFrgrjHtS1IPYzkSqKpdSa4AvgEsAdZV1aPj2JekfsZ2TaCq7gbuHtfrSxoNvzEoNc4QkBpnCEiNMwSkxhkCUuMMAalxhoDUOENAapwhIDXOEJAaZwhIjTMEpMYZAlLjDAGpcYaA1DhDQGqcISA1zhCQGjfnEEiyIsm/JXksyaNJruzGr0myNcmD3e280ZUradT6/MbgLuATVfVAksOBjUnWd9uuq6rP9i9P0rjN+UigqrZV1QPd8g+B7zPoPCTpF7j2H7/K0qXLWbp0OSeddOqkyxnNNYEkxwO/AfxXN3RFkoeSrEty5Cj2IS0Wr/3o/9i583l27nyel1/ePuly+odAkl8Gvgr8SVW9ClwPnAisBrYB187yvKkkG5Js6FuDpLnr1XcgycEMAuDLVfXPAFW1fWj7jcC/zPRc25CpVR/44Jnkhq8A8LbD3jbhanqEQJIA/wB8v6r+Zmh8eVVt61YvAB7pV6K0uJx54kmceeJJky7jTX2OBH4T+EPg4SQPdmOfBC5KshooYDNwaY99SBqzOYdAVf0HkBk22XpMOoD4jUGpcYaA1DhDQGqcISA1zhCQ5tln/v5WDj74UA4++FDe/vaVky6n35eFJL11b+zeza5drwO8eT9JHglIjfNIQJpnF57/QY5/938CcOghB0+4GkNAmncnLVvGScuWTbqMN3k6IDXOEJAaZwhIjTMEpMYZAlLjDAGpcYaA1DhDQGqcISA1zhCQGtf7a8NJNgM/BHYDu6rq9CRLgduA4xn82OiFVbWz774kjd6ojgTeX1Wrq+r0bv0q4J6qWgXc061LWoDG9Q+I1gBnd8s3A/8O/NmY9iWNzHfWf4srd78x6TLmVar6Nf9J8gywk0Gfgb+rqhuSvFxVR3TbA+ycXh963hQw1a2e1qsISftj49DR+ptGcSTw3qramuQYYH2Sx4c3VlXN1GbMNmTSwtD7mkBVbe3udwB3AGcA25Msh0FbMmBH3/1IGo9eIZDksCSHTy8DH2bQe/Au4OLuYRcDd/bZj6Tx6Xs6sAy4Y3Daz0HAV6rq60nuB25PcgnwLHBhz/1IGpPeFwZHUoTXBKT5MOOFQb8xKDXOEJAaZwhIjTMEpMYZAlLjDAGpcYaA1DhDQGqcISA1zhCQGmcISI0zBKTGGQJS4wwBqXGGgNQ4Q0BqnCEgNc4QkBo3598YTPIuBq3Gpp0A/AVwBPDHwP9045+sqrvnuh9J4zWS3xhMsgTYCpwJfAz436r67Ft4vr8xKI3fWH9j8APAU1X17IheT9I8GVUIrAVuGVq/IslDSdYlOXKmJySZSrIhyYYR1SBpDkbRi/AQ4L+BU6pqe5JlwAsMehN+GlheVR/fx2t4OiCN39hOB84FHqiq7QBVtb2qdlfVG8CNDNqSSVqgRhECFzF0KjDdg7BzAYO2ZJIWqF5tyLr+gx8CLh0a/qskqxmcDmzeY5ukBcY2ZFI7bEMmaW+GgNQ4Q0BqnCEgNc4QkBpnCEiNMwSkxhkCUuMMAalxhoDUOENAapwhIDXOEJAaZwhIjTMEpMYZAlLjDAGpcYaA1Lj9CoGuf8COJI8MjS1Nsj7Jk939kd14knwuyaau98Cp4ypeUn/7eyRwE3DOHmNXAfdU1Srgnm4dBj9Bvqq7TQHX9y9T0rjsVwhU1b3AS3sMrwFu7pZvBs4fGv9SDdwHHLHHz5BLWkD6XBNYVlXbuuXngWXd8rHAc0OP29KNSVqAevUdmFZV9VZ/NjzJFIPTBUkT1OdIYPv0YX53v6Mb3wqsGHrccd3Yz6mqG6rq9Jl+B13S/OkTAncBF3fLFwN3Do1/tPuU4D3AK0OnDZIWmqra541Br8FtwE8ZnONfAvwKg08FngS+BSztHhvg88BTwMPA6fvx+uXNm7ex3zbM9P+fbcikdtiGTNLeDAGpcYaA1DhDQGqcISA1zhCQGmcISI0zBKTGGQJS4wwBqXGGgNQ4Q0BqnCEgNc4QkBpnCEiNMwSkxhkCUuMMAalx+wyBWVqQ/XWSx7s2Y3ckOaIbPz7JT5I82N2+OMbaJY3A/hwJ3MTeLcjWA++uql8HfgBcPbTtqapa3d0uG02ZksZlnyEwUwuyqvpmVe3qVu9j0FtA0gFoFNcEPg7869D6yiTfS/LtJGeN4PUljVGvNmRJ/hzYBXy5G9oGvKOqXkxyGvC1JKdU1aszPNc2ZNICMOcjgSR/BPw28Ac13UGk6rWqerFb3sigAck7Z3q+bcikhWFOIZDkHOBPgd+pqh8PjR+dZEm3fAKwCnh6FIVKGo99ng4kuQU4GzgqyRbgUww+DTgUWJ8E4L7uk4D3AX+Z5KfAG8BlVfXSjC8saUGwDZnUDtuQSdqbISA1zhCQGmcISI0zBKTGGQJS4wwBqXGGgNQ4Q0BqnCEgNc4QkBpnCEiNMwSkxhkCUuMMAalxhoDUOENAapwhIDVurm3Irkmydajd2HlD265OsinJE0k+Mq7CJY3GXNuQAVw31G7sboAkJwNrgVO653xh+teHJS1Mc2pD9gusAW7t+g88A2wCzuhRn6Qx63NN4IquK/G6JEd2Y8cCzw09Zks3JmmBmmsIXA+cCKxm0Hrs2rf6AkmmkmxIsmGONUgagTmFQFVtr6rdVfUGcCM/O+TfCqwYeuhx3dhMr2EbMmkBmGsbsuVDqxcA058c3AWsTXJokpUM2pB9t1+JksZprm3Izk6yGihgM3ApQFU9muR24DEG3Yovr6rdY6lc0kjYhkxqh23IJO3NEJAaZwhIjTMEpMYZAlLjDAGpcYaA1DhDQGqcISA1zhCQGmcISI0zBKTGGQJS4wwBqXGGgNQ4Q0BqnCEgNc4QkBo31zZktw21INuc5MFu/PgkPxna9sUx1i5pBPb5Q6MM2pD9LfCl6YGq+r3p5STXAq8MPf6pqlo9ovokjdk+Q6Cq7k1y/EzbkgS4EPitEdclaZ70vSZwFrC9qp4cGluZ5HtJvp3krJ6vL2nM9ud04Be5CLhlaH0b8I6qejHJacDXkpxSVa/u+cQkU8BUz/1L6mnORwJJDgJ+F7hteqzrRvxit7wReAp450zPtw2ZtDD0OR34IPB4VW2ZHkhydJIl3fIJDNqQPd2vREnjtD8fEd4CfAd4V5ItSS7pNq3l508FAN4HPNR9ZPhPwGVV9dII65U0YrYhk9phGzJJezMEpMYZAlLjDAGpcYaA1DhDQGqcISA1zhCQGmcISI0zBKTGGQJS4wwBqXGGgNQ4Q0BqnCEgNc4QkBpnCEiNMwSkxhkCUuMMAalxhoDUOENAalzfNmSj8gLwo+5+sTmKxTkvWLxzW6zz+rWZBhdE3wGAJBsWY0uyxTovWLxzW6zzmo2nA1LjDAGpcQspBG6YdAFjsljnBYt3bot1XjNaMNcEJE3GQjoSkDQBEw+BJOckeSLJpiRXTbqevpJsTvJwkgeTbOjGliZZn+TJ7v7ISde5L0nWJdmR5JGhsRnnkYHPde/hQ0lOnVzl+zbL3K5JsrV73x5Mct7Qtqu7uT2R5COTqXp8JhoCSZYAnwfOBU4GLkpy8iRrGpH3V9XqoY+ZrgLuqapVwD3d+kJ3E3DOHmOzzeNcYFV3mwKun6ca5+om9p4bwHXd+7a6qu4G6P4e1wKndM/5Qvd3u2hM+kjgDGBTVT1dVa8DtwJrJlzTOKwBbu6WbwbOn1wp+6eq7gVe2mN4tnmsAb5UA/cBRyRZPi+FzsEsc5vNGuDWqnqtqp4BNjH4u100Jh0CxwLPDa1v6cYOZAV8M8nGJFPd2LKq2tYtPw8sm0xpvc02j8XyPl7Rnc6sGzplWyxzm9WkQ2Axem9VncrgEPnyJO8b3liDj2MO+I9kFss8hlwPnAisBrYB1060mnk06RDYCqwYWj+uGztgVdXW7n4HcAeDQ8ft04fH3f2OyVXYy2zzOODfx6raXlW7q+oN4EZ+dsh/wM9tXyYdAvcDq5KsTHIIgwswd024pjlLcliSw6eXgQ8DjzCY08Xdwy4G7pxMhb3NNo+7gI92nxK8B3hl6LThgLDHNYwLGLxvMJjb2iSHJlnJ4OLnd+e7vnGa6L8irKpdSa4AvgEsAdZV1aOTrKmnZcAdSWDw3/YrVfX1JPcDtye5BHgWuHCCNe6XJLcAZwNHJdkCfAr4DDPP427gPAYXzX4MfGzeC34LZpnb2UlWMzjF2QxcClBVjya5HXgM2AVcXlW7J1D22PiNQalxkz4dkDRhhoDUOENAapwhIDXOEJAaZwhIjTMEpMYZAlLj/h+34glp0e6I/wAAAABJRU5ErkJggg==\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(1.0, 2.0) [(175, 25), (175, 35)]\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(2.0, 1.0) [(25, 25), (35, 25)]\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(1.0, 2.0) [(25, 175), (25, 165)]\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(2.0, 1.0) [(175, 175), (165, 175)]\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# i set spacing to be some dummy\n",
    "spacing=(1.0,2.0)\n",
    "for i in range(8):\n",
    "    res_img, res_spacing, res_centers = rotate(black_white, spacing=spacing, centers=centers, rotate_id=i)\n",
    "    print(res_spacing, res_centers)\n",
    "    plt.imshow(res_img, cmap=plt.cm.bone)\n",
    "    plt.show()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "As you can see, all possible rotations have been made!"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Finally!\n",
    "Putting these 3 transforms, we have a great augmentation tool!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [],
   "source": [
    "def get_augmented_cube(img: np.array, radii: list, centers: list, main_nodule_idx: int, spacing: tuple, block_size=128,\n",
    "                       pad_value=106, margin=10, rot_id=None):\n",
    "    scale_factor = np.random.random() / 2 + .75\n",
    "    rotate_id = np.random.randint(0, 24) if not rot_id else rot_id\n",
    "    img1, spacing1, centers1, radii1 = scale(img, scale_factor=scale_factor, spacing=spacing, centers=centers,\n",
    "                                             radii=radii)\n",
    "    img2, centers2 = random_crop(img=img1, centers=centers1, radii=radii1, main_nodule_idx=main_nodule_idx,\n",
    "                                 spacing=spacing1, block_size=block_size, pad_value=pad_value, margin=margin)\n",
    "    \n",
    "    existing_centers_in_patch = []\n",
    "    for i in range(len(centers2)):\n",
    "        dont_count = False\n",
    "        for ax in centers2[i]:\n",
    "            if not (0 <= ax <= block_size):\n",
    "                dont_count = True\n",
    "                break\n",
    "        if not dont_count:\n",
    "            existing_centers_in_patch.append(i)\n",
    "    img3, spacing2, centers3 = rotate(img=img2, spacing=spacing1, centers=centers2, rotate_id=rotate_id)\n",
    "    return img3, radii1, centers3, spacing2, existing_centers_in_patch\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [],
   "source": [
    "black_white = np.zeros((200,200))\n",
    "centers = [(25,25), (25,35)]\n",
    "for i in range(50):\n",
    "    black_white[i, 0:50] = np.ones(50)\n",
    "\n",
    "# creating fake nodule\n",
    "for center in centers:\n",
    "    for i in [-1,0,1]:\n",
    "        for j in [-1,0,1]:\n",
    "            black_white[center[0] + i, center[1] + j] = 0.\n",
    "black_white2, radii2, centers2, spacing2, existing_centers_in_patch = get_augmented_cube(black_white, radii=[1.,1.], centers=centers, main_nodule_idx=0, spacing=(1.,1.), block_size = 100, pad_value=0, margin = 10, rot_id=5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[(41, 75), (52, 75)]\n",
      "Which nodules exist in the final patch: [0, 1]\n"
     ]
    }
   ],
   "source": [
    "from matplotlib import pyplot as plt\n",
    "plt.imshow(black_white, cmap=plt.cm.gray)\n",
    "plt.show()\n",
    "\n",
    "plt.imshow(black_white2, cmap=plt.cm.gray)\n",
    "plt.show()\n",
    "print(centers2)\n",
    "print('Which nodules exist in the final patch:', existing_centers_in_patch)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Tadaaa! This is our amazing result!:)\n",
    "\n",
    "\n",
    "I emphasize once again that this process has been done with 2d image, But works for the 3d images of LUNA16 too! (It was trivial because our mission was to augment the LUNA16;) )\n",
    "\n",
    "I showed you this procedure in 2d because the 3d image has got some difficulty in showing the results.\n",
    "\n",
    "However, to see the results of 3d read [How to use](https://github.com/s-mostafa-a/Luna16#how-to-use) section of README.md."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
